﻿/**
* Класс имитирует компонент из AS2
* @author firsoff maxim, email: firsoff_maxim@mail.ru, icq:235859730, tel:+79222345364
* @version 0.1/19.03.2008 15:38
*/

package ru.vega_int.firsoff.as3.components 
{
	import fl.transitions.Tween;
	import flash.display.Shape;
	import flash.display.Sprite;
	import fl.transitions.easing.*;
	import fl.transitions.TweenEvent;
	import fl.motion.easing.Exponential;
	import flash.errors.IllegalOperationError;
	import flash.ui.Mouse;
	import flash.events.*;
	import ru.vega_int.firsoff.as3.events.AccordionEvent;
	//import mx.containers.Accordion;
	public class Accordion extends Sprite
	{
		//	PROPERTIES
		private var _width:Number;				//	ширина, высота, радиус скругления
		private var _height:Number;				//	самого компонента
		private var _radius:Number;
		
		private var _activeWidth:Number;		//	ширина, высота активной области - 
		private var _activeHeight:Number;		//	там где весь активный контент
		
		private var _bars:Array;				//	массив баров
		private var _areas:Array;				//	массив площадей
		private var _canvas:Sprite;				//	канва для отображения баров
		private var _mask:Shape;				//	маска для баров
		private var _tween:Tween;
		private var _tweenObject:Object;		//	объект для твина, чтобы не запрягать какой то отдельный бар
		private var _tweenItems:Array;			//	массив объектов, которые твинятся
		
		private var _easing:Function = Exponential.easeIn;
		private var _easingOpen:Function = Exponential.easeIn;
		private var _easingClose:Function = Exponential.easeOut;
		private var _duration:Number = 0.3;
		private var _mEvent:MouseEvent;	
		public var selected:AccordionHeader;	//	выделенный заголовок
		
		//------------------------------------------------------------------------
		public function Accordion(w:Number, h:Number, rad:Number=5) 
		{
			_width = w;
			_height = h;
			_radius = rad;
			init();
		};
		
		//	METHODS
		private function init() :void
		{
			_activeWidth = _width
			_activeHeight = _height;
			_bars = new Array();
			_areas = new Array();
			_tweenItems = new Array();
			createMask();
			createCanvas() ;
			_tweenObject = new Object();
			_tweenObject.y = 0;
			_mEvent = new MouseEvent(MouseEvent.MOUSE_MOVE);
		};
		
		/**
		 * Создание маски
		 */
		private function createMask() :  void
		{
			_mask = new Shape();
			_mask.visible = false;
			addChild(_mask);
			drawMask();
		};
		/**
		 * Отрисовка маски
		 */
		private function drawMask() : void
		{
			_mask.graphics.clear();
			_mask.graphics.beginFill(0x000000);
			_mask.graphics.drawRoundRect(0, 0, _width, _height, _radius);
			_mask.graphics.endFill();
		};
		
		/**
		 * СОздание канвы для баров
		 */
		private function createCanvas() :  void
		{
			_canvas = new Sprite();
			addChild(_canvas);
			_canvas.mask = _mask;			//	вешаем маску
		};
		/**
		 * Подсчет активной области
		 */
		private function calcActiveArea():void
		{
			
		};
		
		private function getHeadersHeight() : Number
		{
			var ret:Number = 0;
			for (var i:int = 0; i < _bars.length; i++) 
			{
				ret += AccordionHeader(_bars[i]).headerHeight;
			};
			return ret;
		};
		/**
		 * Добавление в сборку бара
		 */
		public function addBar(bar:AccordionHeader) : void
		{
			//	подсчитаем позицию для установки
			var posY:Number = 0;
			if(_bars.length){posY = _height - bar.headerHeight;}//getHeadersHeight();};
			else{selected = bar};
			bar.y = Math.round(posY);
			bar.moveEnable = Boolean(_bars.length);
			bar.state = Boolean(!_bars.length);
			bar._header.buttonMode = bar._header.useHandCursor = true;
			_bars.push(bar);
			_canvas.addChild(bar);
			_activeHeight = _height - getHeadersHeight();
			bar.setMask(_activeWidth, _activeHeight);
			//	перераспределяем
			for (var i:int = 0; i < _bars.length - 1; i++) 
			{
				if(_bars[i].moveEnable)
				{
					_bars[i].y -= Math.round(bar.headerHeight);
				};
			};
			//	добавляем  слушателя для каждого бара
			bar.addEventListener(AccordionEvent.ON_HEADER_CLICK, handleClickBar);
		};
		//------------------------------------------------------------------------
		
		//	GETTERS/SETTERS
		public function set easyOpen(value:Function) : void
		{
			_easingOpen = value;
		};
		
		public function set easyClose(value:Function) : void
		{
			_easingClose = value;
		};
		public function set duration(value:Number) : void
		{
			if(value > 0) {_duration = value}
			else{throw new IllegalOperationError('param + [value] = ' + value + ' less then 0');};
		};
		//------------------------------------------------------------------------
		
		//	HANDLERS
		private function handleClickBar(e:AccordionEvent) : void 
		{
			//trace('!!!!!!!!!!')
			//trace(e.target)
			//mouseEnabled = false;
			//ena = false;
			mouseChildren = false;
			
			var aB:AccordionHeader = AccordionHeader(e.target);
			var start:Number = aB.y;
			var end:Number;
			_tweenItems = new Array();
			aB.mouseEnabled = false;
			//	определяем где находится выделенный бар, выше или ниже открытого в данный момент
			if (aB.y > selected.y)
			{
				_easing = _easingOpen;
				
				//	если ниже, определяем бары выше кликнутого, до выделенного + кликнутый
				for (var i:int = 0; i < _bars.length; i++) 
				{
					//trace(_bars[i].y, selected)
					if(_bars[i].y <  aB.y && _bars[i] != selected && _bars[i].moveEnable && _bars[i].y > selected.y )
					{
						_bars[i].savePosY = Math.round(_bars[i].y);
						_tweenItems.push(_bars[i]);
					};
				};
				aB.savePosY = Math.round(aB.y);
				_tweenItems.push(aB);
				end = Math.round(start - _activeHeight);	
			}
			else 
			{
				_easing = _easingClose;
				//	если выше чем выделенный бар, определяем все бары ниже до выделенного включительно, эти бары 
				//	необходимо сдвигать вниз
				
				for (var k:int = 0; k < _bars.length; k++) 
				{
					if(_bars[k].y >  aB.y  && _bars[k].moveEnable && _bars[k].y <= selected.y  )
					{
						_bars[k].savePosY = Math.round(_bars[k].y);
						_tweenItems.push(_bars[k]);
						
					};
				};
				//trace('_tweenItems : ' + _tweenItems.length)
				end = Math.round(start + _activeHeight);
			};
			
			_tweenObject.y = start;
			
			_tween = new Tween(_tweenObject, 'y', _easing, start, end, _duration, true);
			_tween.addEventListener(TweenEvent.MOTION_CHANGE, handleTweenChange);
			_tween.addEventListener(TweenEvent.MOTION_FINISH, handleTweenFinish);
			
			selected.state = false;
			selected = aB;
			selected.state = true;
			this.dispatchEvent(e);
		};
		
		private function handleTweenChange(e:TweenEvent) : void
		{
			var delta:Number = e.position - Tween(e.target).begin;
			var l:uint = _tweenItems.length
			//trace(delta)
			for (var i:int = 0; i < l; i++) 
			{
				//trace(_tweenItems[i].savePosY)
				_tweenItems[i].y = Math.round(_tweenItems[i].savePosY + delta);
			};
			//_mEvent.updateAfterEvent();
		};
		
		private function handleTweenFinish(e:TweenEvent) : void
		{
			mouseChildren = true;
			Tween(e.target).removeEventListener(e.type, handleTweenFinish);
		};
		//------------------------------------------------------------------------
	};
	
};
